package com.bytebuddytest.annotation;

import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.implementation.StubMethod;
import net.bytebuddy.implementation.attribute.MethodAttributeAppender;
import net.bytebuddy.matcher.ElementMatchers;
import org.junit.Assert;
import org.junit.Test;

import java.io.File;
import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * @author yutianhong
 * @version 1.0
 * @since 2023/10/30 14:48
 */
@SuppressWarnings({"resource", "unused"})
public class AttributeAppenderTest {

    @Retention(RetentionPolicy.RUNTIME)
    public @interface SomeAnnotation {
    }

    public static class AnnotatedMethod {
        @SomeAnnotation
        void bar() {
        }
    }

    @Test
    public void testMethodAttributeAppender() throws Exception {
        DynamicType.Unloaded<AnnotatedMethod> unloaded = new ByteBuddy()
                .subclass(AnnotatedMethod.class)
                .method(ElementMatchers.named("bar"))
                .intercept(StubMethod.INSTANCE)
                .attribute(MethodAttributeAppender.ForInstrumentedMethod.INCLUDING_RECEIVER)
                .make();
        save(unloaded);
        Class<? extends AnnotatedMethod> dynamicClass = unloaded.load(ClassLoader.getSystemClassLoader())
                .getLoaded();
        SomeAnnotation annotation = dynamicClass.getDeclaredMethod("bar")
                .getAnnotation(SomeAnnotation.class);
        Assert.assertNotNull(annotation);
    }

    private void save(DynamicType.Unloaded<?> dynamicType) throws IOException {
        @SuppressWarnings("ConstantConditions")
        String folderPath = getClass().getClassLoader().getResource("").getPath() + "save";
        System.out.println("folderPath = " + folderPath);
        dynamicType.saveIn(new File(folderPath));
    }
}
